package com.ksc.storekeeper.client.view.validation;

import com.ksc.storekeeper.client.resources.StoreKeeperResources;

public class ValidatingHelper<T> {

	private boolean required = false;
	private int minRequired = 0;
	private int maxAllowed = 0;
	private boolean numeric = false;
	private boolean alpha = false;
	private boolean alphaNumberic = false;
	public String errorMessage = "";
	private String regex = "";
	private String specificErrorMessage = "";

	private final IsValidatingWidget<T> validatingWidget;

	public ValidatingHelper(IsValidatingWidget<T> validatingWidget) {
		this.validatingWidget = validatingWidget;
	}

	public void setRequired(boolean required) {
		this.required = required;
	}

	private void addError() {
		validatingWidget.asWidget().addStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().error());
	}

	private void addErrorDouble() {
		validatingWidget.asWidget().addStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().errorDouble());
	}

	public Validation validateOnBlur() {
		if (regex != null && !regex.isEmpty()) {
			if (required && validatingWidget.getText().isEmpty()) {
				return getValidationMessage(Validation.REQUIRED);
			}
			if (maxAllowed > 0 && validatingWidget.getText().length() > maxAllowed) {
				return getValidationMessage(Validation.TOO_LONG);
			}
			if (required && minRequired > 0 && validatingWidget.getText().length() < minRequired || !required && minRequired > 0 && !validatingWidget.getText().isEmpty()
					&& validatingWidget.getText().length() < minRequired) {
				return getValidationMessage(Validation.TOO_SHORT);
			}

			if (!validatingWidget.getText().matches(getRegex())) {
				return getValidationMessage();
			}
		}
		return removeInvalid();
	}

	public Validation validate() {
		if (required && validatingWidget.getText().isEmpty()) {
			return getValidationMessage(Validation.REQUIRED);
		}
		// check for whitespace only
		if (required && validatingWidget.getText().startsWith("\\s+")) {
			return getValidationMessage(Validation.WHITESPACES);
		}
		if (maxAllowed > 0 && validatingWidget.getText().length() > maxAllowed) {
			return getValidationMessage(Validation.TOO_LONG);
		}
		if (required && minRequired > 0 && validatingWidget.getText().length() < minRequired || !required && minRequired > 0 && !validatingWidget.getText().isEmpty()
				&& validatingWidget.getText().length() < minRequired) {
			return getValidationMessage(Validation.TOO_SHORT);
		}

		if (numeric && !validatingWidget.getText().isEmpty() && !validatingWidget.getText().matches("^[\\d]+$") && !validatingWidget.getText().matches("(\\d+\\.\\d+)?")) {
			return getValidationMessage(Validation.NOT_NUMERIC);
		}

		if (alpha && !validatingWidget.getText().isEmpty() && !validatingWidget.getText().matches("^[a-zA-Z\\s]+$")) {
			return getValidationMessage(Validation.NOT_ALPHABHETIC);
		}

		if (alphaNumberic && !validatingWidget.getText().isEmpty() && !validatingWidget.getText().matches("[\\w\\s]+")) {
			return getValidationMessage(Validation.NOT_ALPHANUMERIC);
		}
		return removeInvalid();
	}

	/**
	 * For select box
	 * 
	 * @param value
	 * @return
	 */
	public Validation validateListBox(String value) {
		if (required && (value.equals("0") || value.equals(""))) {
			return getValidationMessage(Validation.REQUIRED);
		}
		return removeInvalid();
	}

	/**
	 * For Amount
	 * 
	 * @param value
	 * @return
	 */
	public Validation validateDoubleBox(String value) {
		if (required && value.isEmpty()) {
			addErrorDouble();
			errorMessage = ErrorMessages.getErrorMessage(Validation.REQUIRED.toString());
			return Validation.REQUIRED;
		}
		if (required && !value.isEmpty() && !value.matches("^[\\d]+$") && !value.matches("(\\d+\\.\\d+)?") && !value.matches("(\\.\\d+)?")) {
			addErrorDouble();
			errorMessage = ErrorMessages.getErrorMessage(Validation.NOT_NUMERIC.toString());
			return Validation.NOT_NUMERIC;
		}

		if (required && !value.isEmpty() && value.matches("(\\d+\\.\\d+)?")) {
			value += "0";
			String[] parseValue = value.split("\\.", 2);
			validatingWidget.setText(parseValue[0] + "." + parseValue[1].substring(0, 2));
		}
		if (required && Double.valueOf(validatingWidget.getText()) <= new Double(0)) {
			addErrorDouble();
			errorMessage = ErrorMessages.getErrorMessage(Validation.LESS_THAN_ZERO.toString());
			return Validation.LESS_THAN_ZERO;
		}
		return removeInvalidDouble();
	}

	/**
	 * For email
	 * 
	 * @return
	 */
	public Validation validateEmail() {
		if (required && validatingWidget.getText().isEmpty()) {
			return getValidationMessage(Validation.REQUIRED);
		}
		if (required && !validatingWidget.getText().matches("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[_A-Za-z0-9-]+)")) {
			return getValidationMessage(Validation.INVALID_EMAIL_ID);
		}
		return removeInvalid();
	}

	public Validation validateDoubleBoxWithMinimun(Double value, Double minimumValue) {
		if ((required && value == null) || required && value < minimumValue) {
			addErrorDouble();
			errorMessage = "Minimum " + minimumValue + " Required";
			return Validation.LESS_THAN_MIN_LIMIT;
		}

		validatingWidget.asWidget().removeStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().error());
		return Validation.VALID;
	}

	public Validation validatePin() {
		if (required && validatingWidget.getText().isEmpty()) {
			return getValidationMessage(Validation.REQUIRED);
		}

		if (!validatingWidget.getText().isEmpty() && !validatingWidget.getText().matches("^[\\d]+$") && !validatingWidget.getText().matches("(\\d+\\.\\d+)?")) {
			return getValidationMessage(Validation.NOT_NUMERIC);
		}

		if (minRequired > 0 && validatingWidget.getText().length() < minRequired) {
			clearField();
			return getValidationMessage(Validation.TOO_SHORT);
		}
		if (maxAllowed > 0 && validatingWidget.getText().length() > maxAllowed) {
			clearField();
			return getValidationMessage(Validation.TOO_LONG);
		}

		return removeInvalid();
	}

	public Validation validatePassword() {
		if (required && validatingWidget.getText().isEmpty()) {
			return getValidationMessage(Validation.REQUIRED);
		}
		if (required && !validatingWidget.getText().isEmpty()) {
			if (minRequired > 0 && validatingWidget.getText().length() < minRequired) {
				clearField();
				return getValidationMessage(Validation.TOO_SHORT);
			}
			if (maxAllowed > 0 && validatingWidget.getText().length() > maxAllowed) {
				clearField();
				return getValidationMessage(Validation.TOO_LONG);
			}

			/**
			 * Add criteria for password check below
			 * 
			 */

			// check for whitespaces in text
			if (!validatingWidget.getText().matches("\\S+")) {
				clearField();
				return getValidationMessage(Validation.WHITESPACES);
			}
			if (numeric && !validatingWidget.getText().matches("[0-9]+$")) {
				clearField();
				return getValidationMessage(Validation.PASS_NOT_NUMERIC);
			}

			if (alpha && !validatingWidget.getText().matches("^[a-zA-Z\\s]+$")) {
				clearField();
				return getValidationMessage(Validation.PASS_NOT_ALPHABHETIC);
			}

			if (alphaNumberic && !validatingWidget.getText().matches("[\\w\\s]+")) {
				clearField();
				return getValidationMessage(Validation.PASS_NOT_ALPHANUMERIC);
			}
		}
		return removeInvalid();
	}

	public void clearField() {
		this.validatingWidget.setText("");
	}

	public Validation validateDate(String date) {
		if (required && date.isEmpty()) {
			return getValidationMessage(Validation.REQUIRED);
		}
		return removeInvalid();
	}

	private Validation getValidationMessage() {
		addError();
		errorMessage = getSpecificErrorMessage();
		return Validation.INVALID_TYPE;
	}

	private Validation getValidationMessage(Validation validation) {
		addError();
		errorMessage = ErrorMessages.getErrorMessage(validation.toString());
		return validation;
	}

	public void showInvalid() {
		validatingWidget.asWidget().addStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().error());
	}

	public Validation removeInvalid() {
		errorMessage = "";
		validatingWidget.asWidget().removeStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().error());
		return Validation.VALID;
	}

	public Validation removeInvalidDouble() {
		errorMessage = "";
		validatingWidget.asWidget().removeStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().errorDouble());
		return Validation.VALID;
	}

	public void setMinLength(int length) {
		this.minRequired = length;
	}

	public void setMaxLength(int length) {
		this.maxAllowed = length;
	}

	public void setNumeric(boolean numeric) {
		this.numeric = numeric;
	}

	public void setAlpha(boolean alpha) {
		this.alpha = alpha;
	}

	public void setAlphaNumeric(boolean alpha) {
		this.alphaNumberic = alpha;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public String getRegex() {
		return regex;
	}

	public void setRegex(String regex) {
		this.regex = regex;
	}

	public String getSpecificErrorMessage() {
		return specificErrorMessage;
	}

	public void setSpecificErrorMessage(String specificErrorMessage) {
		this.specificErrorMessage = specificErrorMessage;
	}

}